class TheFallenMight_SquadAIController extends AIController;

 /*	 ================================================
 *   ===============   variables   ==================
 *   ================================================
 */
// Destination to move to
var Vector Destination;
// Current focus spot
var Vector FocusSpot;
// Debug
var String StateLabel;
// Previous state name
var String CachedPreviousStateName;

/*	 ================================================
 *   ===============    Startup    ==================
 *   ================================================
 */
event PostBeginPlay()
{
    super.PostBeginPlay();
	`Log(SELF.Name);
    //AddDefaultInventory(); //GameInfo calls it only for players, so we have to do it ourselves for AI.
}
/*	 ================================================
 *   ===============   Functions   ==================
 *   ================================================
 */
/**
 * Called from the HUD class to render debug state
 */
simulated function RenderDebugState(UDKRTSHUD HUD)
{
	local Vector V;
	local string Text;
	local float XL, YL;

	// Display the AI states
	if (HUD.ShouldDisplayDebug('AIStates'))
	{
		V = Pawn.Location + Pawn.CylinderComponent.CollisionHeight * Vect(0.f, 0.f, 1.f);
		V = HUD.Canvas.Project(V);		
		HUD.Canvas.Font = class'Engine'.static.GetTinyFont();

		// Render the state debug
		Text = String(GetStateName())@"-"@StateLabel;
		HUD.Canvas.TextSize(Text, XL, YL);
		HUD.DrawBorderedText(HUD, V.X - (XL * 0.5f), V.Y - (YL * 3.f), Text, class'HUD'.default.WhiteColor, class'UDKRTSPalette'.default.BlackColor);

		HUD.Canvas.TextSize("Previous state - "$CachedPreviousStateName, XL, YL);
		HUD.DrawBorderedText(HUD, V.X - (XL * 0.5f), V.Y - (YL * 2.f), "Previous state - "$CachedPreviousStateName, class'HUD'.default.WhiteColor, class'UDKRTSPalette'.default.BlackColor);

		//// Render the enemy debug text
		//if (EnemyTargetInterface != None && EnemyTargetInterface.IsValidTarget())
		//{
		//	Text = "Target = "$EnemyTargetInterface.GetActor();
		//	HUD.Canvas.TextSize(Text, XL, YL);
		//	HUD.DrawBorderedText(HUD, V.X - (XL * 0.5f), V.Y - YL, Text, class'HUD'.default.WhiteColor, class'UDKRTSPalette'.default.BlackColor);
		//}

		//if (IsTimerActive(NameOf(HarvestTimer)))
		//{
		//	Text = "Harvesting resource = "$GetRemainingTimeForTimer(NameOf(HarvestTimer));
		//	HUD.Canvas.TextSize(Text, XL, YL);
		//	HUD.DrawBorderedText(HUD, V.X - (XL * 0.5f), V.Y, Text, class'HUD'.default.WhiteColor, class'UDKRTSPalette'.default.BlackColor);
		//}
	}

	// Display the AI focus
	if (HUD.ShouldDisplayDebug('AIFocus'))
	{
		HUD.Draw3DLine(Pawn.Location, FocusSpot, class'HUD'.default.GreenColor);
	}
}

/**
 * Commands the unit to move to a point in the world
 *
 * @param		MovePoint				World location to move the unit to
 * @param		DisableAutomation		True if you want to disable automation while executing this command
 */
function MoveToPoint(Vector MovePoint, optional bool DisableAutomation)
{
	// If disabling automation, clear the WhatToDo timer
	//if (DisableAutomation && IsTimerActive(NameOf(WhatToDo)))
	//{
	//	ClearTimer(NameOf(WhatToDo));
	//}

	// Move to a point in the world
	Destination = MovePoint;	
	FocusSpot = MovePoint;
	SetDestinationPosition(Destination);
	Resource = None;

	if (!HasReachedPoint(Destination))
	{
		GotoState('MovingToPoint');
	}
}

/**
 * Returns true if the pawn has reached a point in the world
 *
 * @return		Returns true if the pawn has reached a point in the world
 */
function bool HasReachedPoint(Vector Point, optional float Range = -1.f)
{
	if (Pawn == None)
	{
		return false;
	}

	return (VSize2D(Pawn.Location - Point) <= ((Range == -1.f) ? Pawn.GetCollisionRadius() : Range));
}
/**
 * Checks the rotation of a pawn and adjusts movement speed accordingly. If a pawn needs to turn to face a direction before moving, it sets the ground speed to zero
 * This is mostly used by vehicles
 */
simulated function CheckRotation()
{
	local TheFallenMight_Pawn TheFallenMight_Pawn;

	TheFallenMight_Pawn=TheFallenMight_Pawn(Pawn);
	if (TheFallenMight_Pawn != None)
	{
		TheFallenMight_Pawn.GroundSpeed = (TheFallenMight_Pawn.NeedsToTurnWithPrecision(GetDestinationPosition(), TheFallenMight_Pawn.MustFaceDirectionBeforeMovingPrecision)) ? 0.f : TheFallenMight_Pawn.CurrentGroundSpeed;
	}
}


/*	 ================================================
 *   ===============     States     =================
 *   ================================================
 */
/**
 * This state represents the pawn moving some where
 */
state MovingToPoint
{
	/**
	 * Returns if the unit is considered to be idle or not
	 *
	 * @return			Returns if the unit is considered to be idle or not
	 */
	simulated function bool IsIdle()
	{
		return false;
	}

	/**
	 * Renders any debug information required for this AI controller
	 *
	 * @param			HUD			HUD to render the debug information to
	 */
	simulated function RenderDebugState(TheFallenMight_HUD HUD)
	{
		Global.RenderDebugState(HUD);

		// Do we need to render the movement lines or not?
		if (HUD.ShouldDisplayDebug('AIMovementLines'))
		{
			// Draw the current move location
			HUD.Draw3DLine(Pawn.Location, GetDestinationPosition(), class'HUD'.default.GreenColor);
			// Draw the final destination location
			HUD.Draw3DLine(Pawn.Location, Destination, class'UDKRTSPalette'.default.YellowColor);
		}
	}

	/**
	 * Called when this state is first started
	 *
	 * @param			PreviousStateName			Name of the previous state
	 */
	event BeginState(Name PreviousStateName)
	{
		local TheFallenMight_Pawn TheFallenMight_Pawn;

		// Check the rotation @fixme
		TheFallenMight_Pawn = TheFallenMight_Pawn(Pawn);
		if (TheFallenMight_Pawn != None/* && TheFallenMight_Pawn.MustFaceDirectionBeforeMoving*/)
		{
			CheckRotation();
			SetTimer(0.05f, true, NameOf(CheckRotation));
		}
	}

	/**
	 * Called when this state is about to end
	 *
	 * @param			NextStateName				Name of the next state
	 */
	event EndState(Name NextStateName)
	{
		CachedPreviousStateName = "MovingToPoint";
		
		// Restart the WhatToDo timer
		if (!IsTimerActive(NameOf(WhatToDo)))
		{
			SetTimer(0.05f, true, NameOf(WhatToDo));
		}
	}

Begin:
	StateLabel = "Begin";
	// If the pawn is no longer valid then go to the Dead state
	if (!IsValidPawn(Pawn))
	{
		GotoState('Dead');
	}
	// Wait until we are walking again
	if (Pawn.Physics != Pawn.WalkingPhysics)
	{
		Sleep(0.f);
		Goto('Begin');
	}
	//Set the focus spot
	FocusSpot = GetDestinationPosition();
MoveDirect:
	StateLabel = "MoveDirect";
	// Check if the point is directly reachable or not
	if (IsPointReachable(GetDestinationPosition()))
	{
		// Adjust if we need to
		if (bAdjusting)
		{
			SetDestinationPosition(GetAdjustLocation());
		}

		// Move to the destination position
		bPreciseDestination = true;
		FocusSpot = GetDestinationPosition();
		Sleep(0.f);
		Goto('HasReachedDestination');
	}
MoveViaPathFinding:
	StateLabel = "MoveViaPathFinding";
	// Generate the path and get the next move location
	if (GeneratePathTo(GetDestinationPosition(), Pawn.GetCollisionRadius(), true) && NavigationHandle.GetNextMoveLocation(NextMoveLocation, Pawn.GetCollisionRadius()))
	{
		if (bAdjusting)
		{
			// Adjust if we need to
			SetDestinationPosition(GetAdjustLocation());
		}
		else
		{
			// Set the destination to the next move location
			SetDestinationPosition(NextMoveLocation);
		}
		
		// Move towards the destination
		bPreciseDestination = true;
		FocusSpot = GetDestinationPosition();
	}
	else
	{
		Goto('End');
	}
HasReachedDestination:
	// Check if the unit has reached the destination
	StateLabel = "HasReachedDestination";
	if (!HasReachedPoint(GetDestinationPosition()))
	{
		// Reached current destination 
		Sleep(0.f);
		Goto('Begin');
	}
	else if (!HasReachedPoint(Destination))
	{		
		SetDestinationPosition(Destination);
		Sleep(0.f);
		Goto('Begin');
	}
End:
	StateLabel = "End";
	GotoState('');
}

DefaultProperties
{
}

